import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeSet;


public class Graphe {
	ArrayList<Sommet> listeDesSommets;
	
	public Graphe(){
		listeDesSommets=new ArrayList<Sommet>();
	}
	
	public String toString() {
		StringBuilder sb = new StringBuilder();
		for (Sommet s : listeDesSommets)
		{
			sb.append(s);
		    
		}

		return "Graphe Liste Des Sommet(s):\n" +""+  (sb.toString());
	}
	// Retourne le nombre de sommets du graphe
	public int nbSommets(){
		return listeDesSommets.size();
	}
	
	// Retourne le nombre de voisins sortants
	public int nbArc(){
		int s =0;
		ArrayList <Sommet> j=new ArrayList <Sommet>();
		Iterator <Sommet> it=listeDesSommets.iterator();
		while(it.hasNext()){
			j=it.next().getVoisinSortant();
			s+=j.size();
		}
		return s;
	}
	
	// Retourne l'ensemble des Sommets
	public String ensembleSom(){
		String s="Liste des Sommets : \n";
		Iterator <Sommet> it=listeDesSommets.iterator();
		while(it.hasNext()){
			s+=it.next().getNom()+"  ";
		}
		return s;
	}
	
	// Retourne l'ensemble des sommets triés par nom
	public String trierNom(){
		String s="Liste des Sommets triés par nom :";
		Collections.sort(listeDesSommets, new CompareNom());
		Iterator <Sommet> it=listeDesSommets.iterator();
		while(it.hasNext()){
			s+=it.next().getNom()+" ";
		}
		return s;
	}
	
	// Retourne l'ensemble des sommets triés par degre
	public String trierdegre(){
		String s="Liste des Sommets triés par degré sortant :";
		Collections.sort(listeDesSommets, new CompareDegre());
		Iterator <Sommet> it=listeDesSommets.iterator();
		while(it.hasNext()){
			s+=it.next().getNom()+" ";
		}
	return s;
	}
	
	// Retourn l'ensemble des arc
	public String obtenirArc(){
		String s ="";
		Iterator <Sommet> it=listeDesSommets.iterator();
		while(it.hasNext()){
			Sommet s1=it.next();
			Iterator<Sommet> t=s1.getVoisinSortant().iterator();
			while(t.hasNext()){
				Sommet s2=t.next();
				s=s+s1.getNom()+" --> "+s2.getNom()+"   ";
			}
		}
		return s;
	}
	
	//Ajouter un sommet dans le graphe
	public void ajouterSom(Sommet s1){
		if (listeDesSommets.contains(s1)){
			System.out.println("Ce sommet est deja présent");
		}else{
			listeDesSommets.add(s1);
		}
		
	}
	
	// Supprimer un sommet dans le graphe
	public void supprimerSom(String nom){
		Iterator <Sommet> it=listeDesSommets.iterator();
		while(it.hasNext()){
			Sommet s1=it.next();
			if(s1.getNom()==nom){
				for(int i=0; i<s1.getVoisinSortant().size(); i++){
			s1.getVoisinSortant().remove(i);
		}
				listeDesSommets.remove(s1);
	}
	}
	}
	
	// Info sur sommet via son nom
	public String infoNom(String nom){
		String s="";
			Iterator <Sommet> it=listeDesSommets.iterator();
			while(it.hasNext()){
				Sommet s1=it.next();
				if(s1.getNom()==nom){
					s+=s1.toString();
				}	
			}
			
		return s;
	}
	
	public String ajouterArc(Utilisateur u1, Sommet s1){
		String s="";
		if (!(listeDesSommets.contains(s1)) || !(listeDesSommets.contains(u1))){
			s="Un des sommets n'existe pas dans le graphe";
		}else{
			if (u1.getVoisinSortant().contains(s1)){
				s="Cet utilisateur a deja un arc avec ce sommet";
			}else{
				if (s1 instanceof Page){
					u1.getVoisinSortant().add(s1);	
					((Page) s1).getAdministrateur().add(u1);
					s="L'ajout a bien été effectué";
				}else{
					u1.getVoisinSortant().add(s1);	
					s="L'ajout a bien été effectué";
				}
				
			}
		}
		return s;
		
	}
	
	public String supprimerArc(Utilisateur u1, Sommet s1){
		String s="";
		if (!(listeDesSommets.contains(s1)) || !(listeDesSommets.contains(u1))){
			s="Un des sommets n'existe pas dans le graphe";
		}else{
			if (!(u1.getVoisinSortant().contains(s1))){
				s="Cet utilisateur ne possède pas d'arc avec ce sommet";
			}else{
				if (s1 instanceof Page){
					u1.getVoisinSortant().remove(s1);
					((Page) s1).getAdministrateur().remove(u1);
					s="La suppresion a bien été effectuée";
				}else{
					u1.getVoisinSortant().remove(s1);
					s="La suppresion a bien été effectuée";
				}
			}
			
			
		}	
		return s;
	}
	
	// Affiche le nombre de comptes, le nombre d'utilisateur et le nombre de page du graphe
	public String nbCompte(){
		int u=0;
		int p=0;
		String s="";
		Iterator <Sommet> it=listeDesSommets.iterator();
		while(it.hasNext()){
			if (it.next() instanceof Utilisateur ){
				u++;
			}else{
				p++;
			}
		}
		s="Il y a "+(u+p)+" compte(s): "+u+" utilisateur(s) et "+p+" page(s)";
		return s;
		
	}
	
	// Affiche l'age moyen des utilisateurs
	public String ageMoyen(){
		double u=0;
		double m=0;
		double age=0;
		Sommet s;
		String s1;
		Iterator <Sommet> it=listeDesSommets.iterator();
		while(it.hasNext()){
			s=it.next();
			if (s instanceof Utilisateur ){
				Utilisateur u1 = (Utilisateur)s;
				m+=u1.getAge();
				u++;
			}
	}
		
		age=m/u;
	s1="L'age moyen des utilisateurs est de "+age+" ans";
	return s1;
}
	
	// Affiche les utilisateurs administrateur de page
	public String admin(){
		Iterator <Sommet> it=listeDesSommets.iterator();
		HashSet <Utilisateur> adm =new HashSet<Utilisateur>();
		Sommet s;
		String s1="";
		while(it.hasNext()){
			s=it.next();
			if (s instanceof Page ){
				Page p1 = (Page)s;
				for(int i=0; i<p1.getAdministrateur().size(); i++){
				adm.add(p1.getAdministrateur().get(i));
				}
				
			}
		
	}
		Iterator <Utilisateur> ite=adm.iterator();
		while(ite.hasNext()){
			s1+=(ite.next().getNom())+" ";
		}
		return s1;
	}
	public String PageRank(){
		String s = null;
		double max=0;
		int i=0;
		while (i<=100){
			Iterator <Sommet> it=listeDesSommets.iterator();
			while(it.hasNext()){
				Sommet a=it.next();
				double p=0.15/Math.abs(this.nbSommets())+0.85+VoisinEntrant(a);
				a.setPagerank(p);
		}
		
			i=i+1;
	}
		Iterator <Sommet> it=listeDesSommets.iterator();
		while(it.hasNext()){
			Sommet a=it.next();
			if (a.getPagerank()>max){
				s=a.getNom();
				max=a.getPagerank();
			}
		}
		return s;
		
		
	}
	public double VoisinEntrant(Sommet s1){
		double a=0;
		ArrayList<Double> l;
		l=new ArrayList<Double>();
		l.add(a);
		Iterator <Sommet> it=listeDesSommets.iterator();
		while (it.hasNext()){
			Sommet s2=it.next();
			if (s2.getVoisinSortant().contains(s1)){
			l.add(s2.getPagerank()/s2.getVoisinSortant().size());
			}
			
}
		Iterator <Double> it2=l.iterator();
		while (it2.hasNext()){
			a=a+it2.next();
		}
		return a;
		
		
	}
	
	public String ecrireGraphe(){
	    ObjectOutputStream o2;
	    ObjectInputStream o1 = null;
	    String s="";

	    try {
	      o2 = new ObjectOutputStream( new BufferedOutputStream( new FileOutputStream( new File("graphe.txt"))));
	      o2.writeObject(listeA());
	      o2.close();
	}catch (IOException e){
		e.printStackTrace();
	};
	
	try {
		o1 = new ObjectInputStream(
		        new BufferedInputStream(
		          new FileInputStream(
		            new File("graphe.txt"))));
	} catch (FileNotFoundException e1) {
		
		e1.printStackTrace();
	} catch (IOException e1) {
		
		e1.printStackTrace();
	}
          
    try {
      s="Liste Adjacente :";
      try {
		s+=(o1.readObject()).toString();
	} catch (IOException e) {
		
		e.printStackTrace();
	}
    } catch (ClassNotFoundException e) {
      e.printStackTrace();
    }
	
    try {
		o1.close();
	} catch (IOException e) {
		
		e.printStackTrace();
	}
    return s;
  
  }     		
	
	public String listeA(){
		String s="(";
		Iterator<Sommet> it=listeDesSommets.iterator();
		while (it.hasNext()){
			Sommet s1=it.next();
			s=s+"( "+(s1.getNom()+"("+voisin(s1)+"))");
		}
		return s;
	}

	public String voisin(Sommet s){
		String s1="";
		Iterator<Sommet> it=s.getVoisinSortant().iterator();
		while (it.hasNext()){
			s1=s1+(it.next().getNom()+", ");
	}
		return s1;
	}
	
	/*public void lireGraphe(){
		try{
			FileReader f=new FileReader("graphe.txt");
			BufferedReader br=new BufferedReader(f);
			String line=br.
		}
		
	}*/
	}
